# author：

import configparser
from datetime import datetime
import os
import pickle
import selenium.webdriver.remote.webelement
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from typing import List

cfg = configparser.RawConfigParser()
conf_path = "./config.conf"
cfg.read([conf_path], encoding='utf-8')


class Book_Ticket(object):
    def __init__(self):
        # 首页url
        self.damai_url = "https://www.damai.cn/"
        # 登录界面
        self.login_url = "https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F"
        # 购票界面url
        self.book_url = cfg.get("ticket_info", "book_url").strip()

        self.price_list = cfg.get("ticket_info", "price").strip().split(",")  # 抢票的价格档位，从左向右 1档位对应索引0
        self.price = list(map(int, self.price_list))
        self.name_list = cfg.get("ticket_info", "name_num").strip().split(",")  # 在订单界面选择给第几个实名用户购买，默认给第一个用户购买
        self.name_num = list(map(int, self.name_list))  # 在订单界面选择给第几个实名用户购买，默认给第一个用户购买
        self.buy_num = int(cfg.get("ticket_info", "buy_num").strip())  # 购买数量
        self.session_list = cfg.get("ticket_info", "session").strip().split(",")  # 场次，从左向右
        self.session = list(map(int, self.session_list))

        self.driver_path = cfg.get("other", "driver_path").strip()

        self.status = 0  # 是否登录的状态 0是未登录，1是登录

        self.current_num = 1  # 当前第几次抢票
        self.num = int(cfg.get("ticket_info", "num").strip())  # 抢票总次数

        self.datetime = cfg.get("ticket_info", "date_time").strip()  # 抢票时间点
        self.rush_time = time.strptime(self.datetime, '%Y-%m-%d %H:%M:%S')

        self.xuanzuo = int(cfg.get('setting','xuanzuo')) == 1 #选座信息 演出界面会写能不能选座
        self.shiming = int(cfg.get('setting','shiming')) == 1 #实名信息 购买须知会写实名限制 如果是不需要实名的会写无需实名
        print("选座:{}".format(self.xuanzuo))
        print("实名:{}".format(self.shiming))

        self.chrome_options = webdriver.ChromeOptions()
        # 如果选座已经登陆过 或者不选座 则默认关闭图片
        if os.path.exists("cookies.pkl") and self.xuanzuo == False:
            self.chrome_options.add_argument("--blink-settings=imagesEnabled=false")
            
        self.chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
        self.chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        self.chrome_options.add_argument("--disable-extensions")
        self.chrome_options.add_argument("--disable-dev-shm-usage")
        self.chrome_options.add_argument("--no-sandbox")
        self.chrome_options.add_argument("--disable-setuid-sandbox")
        # 这里写缓存路径 有缓存速度会快点 注释打开记得填写绝对路径 最好写当前脚本的绝对路径
        #self.chrome_options.add_argument('--user-data-dir=')
        # 禁用GPU加速 我感觉加速才可以抢票快点吧

        #self.chrome_options.add_argument('--proxy-server=127.0.0.1:proxy=7890')
        # htmlelement元素树加载好就算完成 不需要等整个页面渲染出来
        self.chrome_options.page_load_strategy = 'eager'
        self.driver = webdriver.Chrome(executable_path=self.driver_path,
                                       options=self.chrome_options)  # 默认谷歌浏览器, 指定下驱动的位置
        self.driver.maximize_window()


    def get_wait_element(self, element: selenium.webdriver, _type: By, param: str) -> selenium.webdriver.remote.webelement.WebElement:
        e = WebDriverWait(element, 5, 0.001).until(EC.presence_of_element_located((_type, param)))
        return e

    def get_wait_elements(self, element: selenium.webdriver, _type: By, param: str) -> List[selenium.webdriver.remote.webelement.WebElement]:
        e = WebDriverWait(element, 5, 0.001).until(EC.presence_of_all_elements_located((_type, param)))
        return e


    def get_cookie(self):
        try:
            # 先进入登录页面进行登录
            print("------开始登录------")
            self.driver.get(self.login_url)
            self.driver.switch_to.frame(0)
            login_methods = self.get_wait_elements(self.driver,By.CLASS_NAME, "login-tabs-tab")
            login_methods[2].click()
            print("------请扫码------")
            while self.driver.title != '大麦网-全球演出赛事官方购票平台-100%正品、先付先抢、在线选座！':
                time.sleep(1)
            print("------扫码成功------")
            pickle.dump(self.driver.get_cookies(), open("cookies.pkl", "wb"))
            print("------Cookie保存成功------")
        except Exception as e:
            raise e

    def set_cookie(self):
        try:
            cookies = pickle.load(open("cookies.pkl", "rb"))  # 载入cookie
            for cookie in cookies:
                cookie_dict = {
                    'domain': '.damai.cn',  # 必须有，不然就是假登录
                    'name': cookie.get('name'),
                    'value': cookie.get('value'),
                    "expires": "",
                    'path': '/',
                    'httpOnly': False,
                    'HostOnly': False,
                    'Secure': False}
                self.driver.add_cookie(cookie_dict)
            print('------载入Cookie------')
        except Exception as e:
            print(f"------cookie 设置失败，原因：{str(e)}------")

    def login(self):
        if not os.path.exists('cookies.pkl'):  # 如果不存在cookie.pkl,就登录获取一下
            self.get_cookie()
        else:  # 存在就设置下cookie
            self.driver.get(self.damai_url)
            self.set_cookie()

    # 票价选择
    def select_price(self):
        try:
            """
            选择场次
            """
            perform_order_box: selenium.webdriver.remote.webelement.WebElement = WebDriverWait(self.driver,10,0.01).until(EC.presence_of_element_located((By.CLASS_NAME,'perform__order__box')))
            riqi = self.driver.find_elements(By.CLASS_NAME,'wh_container')
            changchi_list = perform_order_box.find_elements(By.XPATH,'./div[3]/div[2]/div/div')
            print(f"---------一共有{len(changchi_list)}场次")
            for s in self.session:
                changchi_list[s - 1].click()
                """
                选择票价挡位
                :return: 
                """
                price_list = perform_order_box.find_elements(By.XPATH,'./div[5]/div[2]/div/div')
                # 根据优先级选择一个可行票价
                # 获取场次
                print(f"------票价档次数量：{len(price_list)}------")
                num = 0
                for i in self.price:
                    print(f"------正在抢购第 {str(i)} 挡位票------")
                    try:
                        # 如果购买票数大于1 啧增加
                        if self.buy_num > 1 and not self.xuanzuo:
                            btn_add = perform_order_box.find_element(By.XPATH,
                                                               "./div[6]/div[2]/div/div/a[2]")
                            for index in range(1, self.buy_num):
                                btn_add.click()
                        spans = price_list[i - 1].find_elements(By.TAG_NAME, "span")
                        if len(spans) > 0:
                            print(f"------第 {i} 档票已经售完------")
                        else:
                            price_list[i - 1].click()
                            return
                        num += 1
                        if num < len(self.price):
                            continue
                    except:
                        price_list[i - 1].click()
                        return
                    if num == len(self.price):
                        print(f"------{s}场次票已售完------")
            raise Exception("你想抢的票已售完")
        except Exception as e:
            raise e

    def select_buy_name(self):
        try:
            while self.driver.title != "订单确认页":
                continue
            # 先判断是否有选择购买人的标签
            try:
                if self.shiming:
                    # 需要实名
                    viewer = WebDriverWait(self.driver, 1, 0.01).until(
                        EC.presence_of_element_located((By.CLASS_NAME, 'viewer')))
                    # 获取选中按钮
                    tog_clicks = viewer.find_elements(By.TAG_NAME, "i")
                    print("开始选择观演人")
                    click_1 = True
                    while click_1:
                        try:
                            # 循环遍历数量默认从上到下
                            for i in range(self.buy_num):
                                tog_clicks[self.name_num[i] - 1].click()
                                print(f"选择{self.name_num[i] - 1}号观演人")
                            click_1 = False
                        except Exception as e:
                            raise e
                else:
                    print("不需要实名")
                    return
            except:
                raise Exception("找不到观演人")
        except Exception as e:
            raise e

    # 手动选座
    def select_sear(self):
        if not self.xuanzuo:
            # 不需要选座
            return
        print("请手动选择座位")
        while len(self.driver.find_elements(By.XPATH,
                                            '//*[@id="app"]/div/div[4]/div[1]/div/div/div')) != self.buy_num:
            continue
        buy = self.driver.find_element(By.XPATH, '//*[@id="app"]/div/div[4]/div[2]/button')
        buy.click()

    def submit(self):
        try:
            submit_click = WebDriverWait(self.driver, 5, 0.001).until(EC.presence_of_element_located(
                (By.XPATH, '//*[@id="dmOrderSubmitBlock_DmOrderSubmitBlock"]/div[2]/div/div[2]/div[3]/div[2]')))
            click_2 = True
            while click_2:
                try:
                    submit_click.click()
                    print("提交订单成功")
                    click_2 = False
                except Exception as e:
                    pass
        except Exception as e:
            print(e)
            raise e

    def rush_ticket(self):
        try:
            # 直接来到演唱会购票界面
            self.driver.get(self.book_url)

            buybtn = self.driver.find_elements(By.CLASS_NAME,'buybtn')
            if len(buybtn) != 0 and buybtn[0].text == "即将开抢":
                print("提前刷新，尚未开售")
                raise Exception("尚未开售")

            # 选择票价
            self.select_price()

            # 点击立即预定
            buy_link = self.driver.find_element(By.CLASS_NAME,
                                                "buy-link")
            buy_link.click()

            # 选择座位
            self.select_sear()
            print("开始选择购买人")
            # 选择购买人
            self.select_buy_name()

            # 座位

            print("提交订单")
            # 点击提交订单
            self.submit()

        except Exception as e:
            raise e

    def run(self):
        try:
            # 登录
            self.login()
            # 获取是否需要选座和实名
            time.sleep(2)
            # 判断抢票时间是否到达
            print("------等待抢票时间点到来，进行抢票------")
            while time.mktime(self.rush_time) - time.time() > 0.5:
                time.sleep(0.5)

            start_time = time.time()
            print(f"------开始抢票，时间点：{str(datetime.now())}------")

            # 抢票
            loop = 1
            for i in range(self.num):
                try:
                    print(f"------正在进行第 {str(i + 1)} 轮抢票------")
                    self.rush_ticket()
                    break
                except Exception as e:
                    if loop == self.num:
                        raise e
                    loop += 1
                    pass
            # self.rush_ticket()

            end_time = time.time()
            print(f"抢票结束，时间点：{datetime.now()}")
            print(f"抢票总时长：{(end_time - start_time)}， 不包括登录时间")
            time.sleep(999)

        except Exception as e:
            self.driver.quit()
            print("抢票失败*" % str(e))


if __name__ == '__main__':
    book = Book_Ticket()
    book.run()
